#!/usr/bin/env node

const yargs = require("yargs");
const { Octokit } = require("@octokit/rest");

const GPUWEB_ORG = "gpuweb";
const GPUWEB_REPOSITORY = "gpuweb";

// The identifiers for some columns in the WGSL project.
// You can list all the columns by calling this script with the "project-info" command.

const WGSL_UNDER_DISCUSSION_COLUMN = 8444327;
const WGSL_MEETING_COLUMN = 8898490;

const TOKEN_ENV_NAME = "GPUWEB_GITHUB_TOKEN";

async function authenticate(token) {
    const octokit = new Octokit({ auth: token });
    await octokit.request("/user");
    return octokit;
}

async function agenda(kit, column) {
    console.log("Suggested meeting agenda from Github project.");
    console.log("----");
    const cards = await kit.projects.listCards({ column_id: column });
    for (let card of cards.data) {
        // Notes are agenda topics that don't have an issue.
        if (card.note) {
            console.log(`- ${card.note}`);
        } else {
            // Check if the card is an issue. e.g. https://api.github.com/repos/gpuweb/gpuweb/issues/569
            const url = card.content_url;
            const matches = /gpuweb\/gpuweb\/issues\/(\d+)$/.exec(url);
            if (matches) {
                const issueIdentifier = matches[1];
                const issue = await kit.issues.get({ owner: GPUWEB_ORG, repo: GPUWEB_REPOSITORY, issue_number: issueIdentifier });
                console.log(`- ${issue.data.title.replace(/\s*\[wgsl\]\s*/i, "")} (#${issueIdentifier})`);
                console.log(`  ${issue.data.html_url}`);
            }
        }
        console.log("");
    }
}

async function sortMVP(kit, column) {
    const cards = await kit.projects.listCards({ column_id: column });
    for (let card of cards.data.reverse()) { // Do it in reverse so order is preserved.
        const url = card.content_url;
        const matches = /gpuweb\/gpuweb\/issues\/(\d+)$/.exec(url);
        if (matches) {
            const issueIdentifier = matches[1];
            const issue = await kit.issues.get({ owner: GPUWEB_ORG, repo: GPUWEB_REPOSITORY, issue_number: issueIdentifier });
            if (issue.data.milestone && issue.data.milestone.title == "MVP") {
                console.log(`Moving MVP issue #${issueIdentifier} to top of column`);
                await kit.projects.moveCard({ card_id: card.id, position: "top" });
            }
        }
    }
}

async function projectInfo(kit) {
    const projects = await kit.projects.listForOrg({ org: GPUWEB_ORG });
    for (let project of projects.data) {
        console.log(`Columns for project "${project.name}" (id: ${project.id})`);
        console.log("----");
        const columns = await kit.projects.listColumns({ project_id: project.id });
        for (let column of columns.data) {
            console.log(`${column.name} (id: ${column.id})`);
        }
        console.log("");
    }
}

const argumentProcessor = yargs
    .scriptName("wgsl-meeting-helper")
    .usage("$0 <command>")
    .command({
        command: ["agenda", "$0"],
        desc: "Build the meeting agenda from the WGSL Github Project.",
        handler: () => {
            run(agenda, WGSL_MEETING_COLUMN);
        }
    })
    .command({
        command: "sort-mvp",
        desc: "Sorts the Under Discussion column in WGSL to put MVP topics at the top.",
        handler: () => {
            run(sortMVP, WGSL_UNDER_DISCUSSION_COLUMN);
        }
    })
    .command({
        command: "project-info",
        desc: "Dumps info on the projects in GPUWeb.",
        handler: () => {
            run(projectInfo);
        }
    })
    .version(false)
    .help()
    .epilogue(`Requires a Github Personal Access Token to be provided as the environment variable ${TOKEN_ENV_NAME}.`)

const token = process.env[TOKEN_ENV_NAME];
if (!token) {
    console.log("Error: missing Github Personal Access Token.\n");
    argumentProcessor.showHelp();
    process.exit();
}

async function run(targetFunction, ...args) {
    const kit = await authenticate(token);
    targetFunction(kit, ...args);
}

argumentProcessor.parse();

